package IC.AST.SemanticAnalysis;

import IC.AST.*;
import IC.Error.*;
import IC.Error.Error.ErrorType;
import IC.SymbolTables.Types.MethodType;
import IC.SymbolTables.Types.VoidType;
import IC.SymbolTables.Types.ArrayType;
import IC.SymbolTables.Types.BasicType.BasicTypeEnum;

class CheckOneMainVisitor extends IC.AST.Visitor 
{
	private boolean _isMainFound;
	private String _classID;
	
	public Object Visit(Program rootNode)
	{
		_isMainFound = false;
		VisitSons(rootNode);
		
		if(!_isMainFound)
			return ErrorStack.Push(
					new ErrorString(
							ErrorType.Semantic, 
							"Can't find main function (program entrance point declaration), " +
							"must be with signature 'static void main(string[])"));
		
		return null;
	}
	
	public Object Visit(ClassDeclaration node)
	{
		_classID = node.GetID();
		VisitSons(node);
		
		return null;
	}

	public Object Visit(Method node)
	{
		if(node.GetID().equals("main") && CheckMainSignature((MethodType)node.GetType(), node.IsStatic()))
		{
			if (_isMainFound)
				return ErrorStack.Push(new ErrorStringIntervaled(ErrorType.Semantic, String.format(
						"Can't declare more then one main, redeclaration found in class '%s'", _classID), 
					node.GetInterval()));
			else
				_isMainFound = true;
		}
		return null;
	}
	
	private boolean CheckMainSignature(MethodType signature, boolean isStatic)
	{
		return isStatic
				&& (signature.GetReturnType().equals(new VoidType()))
				&& (signature.GetParamTypes().length == 1)
				&& (signature.GetParamTypes()[0].equals(
						new ArrayType(
								new IC.SymbolTables.Types.BasicType(
										BasicTypeEnum.STRING))));
	}
}
